package com.ce.pms.charge.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IBusinessCodeDao;
import com.ce.pms.charge.dao.IChargeItemDao;
import com.ce.pms.charge.dao.IChargeStaDao;
import com.ce.pms.charge.model.ChargeItemDomain;
import com.ce.pms.charge.service.IChargeItemService;
import com.ce.pms.charge.vo.ChargeItemVO;
import com.ce.pms.common.model.SysInfo;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.dao.IMeterDao;
import com.ce.util.BlankUtil;
import com.sitechasia.webx.core.support.Page;
import com.sitechasia.webx.core.utils.base.PopulateUtil;
/**
 * 功能描述: 收费项目功能处理类
 * <p>版权所有：中企动力
 * <p>未经本公司许可，不得以任何方式复制或使用本程序任何部分
 *
 * @author  胡煦
 * Create on:2008-8-7
 * Edit author:
 * Edit on:
 * 修改原因：

 */

public class ChargeItemServiceImpl extends PmsBaseServiceImpl implements
		IChargeItemService {
	/**
	 * 方法描述: 根据收费项目id查找实体
	 * @author 胡煦
	 * Create on:2008-8-7
	 * @param chargeItemId
	 * @return ChargeItemVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public ChargeItemVO findChargeItemById(Long chargeItemId){
		super.checkParameterIsNull(chargeItemId, "common:parameters_null_exception,ID");
		ChargeItemDomain chargeItemDomain = chargeItemDao.findById(chargeItemId);
		ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
		// 检查收费标准是否被引用，设置相应状态,主要为页面修改操作提供支持
		if(checkChargeItem(chargeItemId)){
			chargeItemVO.setReferSelect(SysrefcodeDO.CONSTANTS_DIGITAL_ONE);
		}
		return chargeItemVO;
	}

	/**
	 * 方法描述:根据收费类型和走表类型查询收费项目
	 * @author 胡煦
	 * Create on:2008-8-22
	 * @param type
	 * @return List<ChargeItemVO>
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public List<ChargeItemVO> queryChargeItemListByType(String chrgType,String meterType){
		List<ChargeItemDomain>  chargeItemDomainList = chargeItemDao.queryChargeItemListByType(chrgType,meterType);
		List<ChargeItemVO> ChargeItemVOList = new ArrayList<ChargeItemVO>(0);
		for(ChargeItemDomain chargeItemDomain : chargeItemDomainList){
			ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
			ChargeItemVOList.add(chargeItemVO);
		}
		return ChargeItemVOList;
	}

	/**
	 * 方法描述: 查询最大的序号
	 * @author 胡煦
	 * Create on:2008-8-21
	 * @param
	 * @return short
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public Short getMaxSeqNo(){
		return chargeItemDao.getMaxSeqNo();
	}

	/**
	 * 方法描述: 根据收费项目名字模糊查询收费项目LIST
	 * @author 胡煦
	 * Create on:2008-8-26
	 * @param chargeItemName
	 * @return List<ChargeItemVO>
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public List<ChargeItemVO> queryChargeItemListByName(String chargeItemName){
		List<ChargeItemDomain>  chargeItemDomainList = chargeItemDao.queryChargeItemListByName(chargeItemName);
		List<ChargeItemVO> ChargeItemVOList = new ArrayList<ChargeItemVO>(0);
		for(ChargeItemDomain chargeItemDomain : chargeItemDomainList){
			ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
			ChargeItemVOList.add(chargeItemVO);
		}
		return ChargeItemVOList;
	}

	/**
	 * 方法描述:根据收费项目id字符串得到收费实体列表,如果传入chargeItemIds为空，则返回所有收费项目，filterSign 为true 则表示chargeItemIds是要过滤的id
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param chargeItemIds 字符串，如：1,2,3; filterSign
	 * @return List
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public List<ChargeItemVO> queryChargeItemList(String chargeItemIds,boolean filterSign){
		List<ChargeItemDomain> list = chargeItemDao.queryChargeItemList(chargeItemIds, filterSign);
		List<ChargeItemVO> ChargeItemVOList = new ArrayList<ChargeItemVO>();
		for(ChargeItemDomain chargeItemDomain : list){
			ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
			ChargeItemVOList.add(chargeItemVO);
		}
		return ChargeItemVOList;
	}

	/**
	 * 方法描述: 查询所有已被引用的收费项目
	 * @author 胡煦
	 * Create on:2008-8-20
	 * @param
	 * @return List<ChargeItemVO>
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public List<ChargeItemVO> queryChargeItemListUsed(){
		List<ChargeItemDomain> list = chargeItemDao.queryChargeItemList(null,false);
		List<ChargeItemVO> ChargeItemVOList = new ArrayList<ChargeItemVO>();
		for(ChargeItemDomain chargeItemDomain : list){
			if((chargeStaDao.queryAllChargeSatBy(chargeItemDomain.getKeyword()).size() > 0)){
				ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
				ChargeItemVOList.add(chargeItemVO);
			}
		}
		return ChargeItemVOList;
	}

	/**
	 *
	 * 功能描述: 得到收费项目及标准树列表。
	 * 将一个收费项目及标准节点和所有的收费项目放入一个Map中，再将Map返回。
	 *
	 * @author 胡煦
	 * Created on:2008-8-1
	 *
	 * 修改原因：
	 * @return List<Map> 返回结果
	 */
	public Map queryChargeItemAndStaTreeList(){

		Map<Object, List<ChargeItemVO>> chargeItemMap = new HashMap<Object, List<ChargeItemVO>>();
		ChargeItemVO chargeItemVO = null;
		List<ChargeItemVO> chargeItemVOList = new ArrayList<ChargeItemVO>();
		chargeItemMap = new HashMap<Object, List<ChargeItemVO>>();
		List<ChargeItemDomain> ChargeItemSet = chargeItemDao.findAll();

		if (!BlankUtil.isBlank(ChargeItemSet)) {

			for (ChargeItemDomain chargeItemDomain : ChargeItemSet) {
				chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
				chargeItemVOList.add(chargeItemVO);
			}
			//ChargeItemVO已实现compareTo接口,添加自身逻辑,在比较时会用ChargeItemVO.seqNo进行比较,升序排列
			Collections.sort(chargeItemVOList);

		}

		chargeItemMap.put("收费项目及标准", chargeItemVOList);

		return chargeItemMap;
	}

	/**
	 * 方法描述: 分页查询收费项目列表,根据传入的不同参数：收费项目名字，序号，创建时间进行排序，传入为null时默认按创建时间排序
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param int, int, String
	 * @return Page
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public Page queryChargeItemByPage(int pageNo,int pageSize,String orderStr){
		Page page = chargeItemDao.queryChargeItemByPage(pageNo, pageSize, orderStr);
		List<ChargeItemDomain> chargeItemDomainList = new ArrayList<ChargeItemDomain>();
		List<ChargeItemVO> chargeItemVOList = new ArrayList<ChargeItemVO>();
		chargeItemDomainList = page.getResult();
		for(ChargeItemDomain chargeItemDomain : chargeItemDomainList){
			ChargeItemVO chargeItemVO = this.convertChargeItemD2V(chargeItemDomain);
			chargeItemVOList.add(chargeItemVO);
		}
		page.setResult(chargeItemVOList);
		return page;
	}

	/**
	 * 方法描述:新增收费项目
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param ChargeItemVO
	 * @return ChargeItemVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public ChargeItemVO addChargeItem(ChargeItemVO chargeItemVO){
		//验证必填项
		checkChargeItemVONotNullField(chargeItemVO,"common:mustFill_null_exception");
		//验证收费项目名称是否重复
		if(checkChargeItemNameIsOnly(chargeItemVO.getItemName(),null)){
			throw new BusinessException("charge:chargeItem_name_exist_exception",BusinessException.WARNING);
		}
		//验证收费项目序号是否重复
		if(checkChargeItemSeqNoIsOnly(chargeItemVO.getSeqNo(),null)){
			throw new BusinessException("charge:chargeItem_seqno_exist_exception",BusinessException.WARNING);
		}
		ChargeItemDomain chargeItemDomain = chargeItemDao.saveObject(this.convertChargeItemV2D(chargeItemVO));
		chargeItemVO.setKeyword(chargeItemDomain.getKeyword());
		return chargeItemVO;
	}
	/**
	 * 方法描述:修改收费项目
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param ChargeItemVO
	 * @return ChargeItemVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public ChargeItemVO editChargeItem(ChargeItemVO chargeItemVO){
		//验证必填项
		checkChargeItemVONotNullField(chargeItemVO,"common:mustFill_null_exception");
		//验证收费项目名称是否重复
		if(checkChargeItemNameIsOnly(chargeItemVO.getItemName(),chargeItemVO.getKeyword())){
			throw new BusinessException("charge:chargeItem_name_exist_exception",BusinessException.WARNING);
		}
		//验证收费项目序号是否重复
		if(checkChargeItemSeqNoIsOnly(chargeItemVO.getSeqNo(),chargeItemVO.getKeyword())){
			throw new BusinessException("charge:chargeItem_seqno_exist_exception",BusinessException.WARNING);
		}
		ChargeItemDomain chargeItemDomain = chargeItemDao.saveOrUpdateObject(this.convertChargeItemV2D(chargeItemVO));
		return chargeItemVO;
	}
	/**
	 * 方法描述:删除收费项目
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param chargeItemId
	 * @return void
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public void deleteChargeItem(Long chargeItemId){
		//验证ID是否为空
		super.checkParameterIsNull(chargeItemId, "common:parameters_null_exception,ID");
		//验证收费项目是否被引用，被引用则不允许删除
		if(checkChargeItem(chargeItemId)){
			throw new BusinessException("common:delete_error_exception",
					BusinessException.WARNING);
		}
		try {
			chargeItemDao.deleteObjectById(chargeItemId);
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 方法描述: 检查收费项目名称是否唯一
	 *  注：新建判断chargeItemName的唯一性时，chargeItemId为null；修改判断chargeItemName的唯一性时，则需要传入修改前的chargeItemId<br>
	 * @author 胡煦
	 * Create on:2008-7-30
	 * @param chargeItemName
	 * @return boolean：返回true表示已经被引用，false则未被引用
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public boolean checkChargeItemNameIsOnly(String chargeItemName,Long chargeItemId){
		super.checkParameterIsNull(chargeItemName, "common:parameters_null_exception,seqNo");
		return chargeItemDao.checkChargeItemNameIsOnly(chargeItemName, chargeItemId) != 0;
	}

	/**
	 * 方法描述: 检查收费项目序号是否唯一
	 *  注：新建判断seqNo的唯一性时，chargeItemId为null；修改判断seqNo的唯一性时，则需要传入修改前的chargeItemId<br>
	 * @author 胡煦
	 * Create on:2008-7-30
	 * @param seqNo，chargeItemId
	 * @return boolean：返回true表示已经被引用，false则未被引用
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public boolean checkChargeItemSeqNoIsOnly(Short seqNo,Long chargeItemId){
		super.checkParameterIsNull(seqNo, "common:parameters_null_exception,seqNo");
		return chargeItemDao.checkChargeItemSeqNoIsOnly(seqNo, chargeItemId) != 0;
	}


	/**
	 * 方法描述: ChargeItemDomain to ChargeItemVO
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param chargeItemDomain
	 * @return ChargeItemVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	private ChargeItemVO convertChargeItemD2V(ChargeItemDomain chargeItemDomain){
		ChargeItemVO chargeItemVO = new ChargeItemVO();
		if(BlankUtil.isBlank(chargeItemDomain)){
			return chargeItemVO;
		}
		PopulateUtil.populate(chargeItemDomain, chargeItemVO);

		chargeItemVO.setMeterTypeDisplay(meterDao.getMeterTypeByCode(chargeItemDomain.getMeterType())==null?null:meterDao.getMeterTypeByCode(chargeItemDomain.getMeterType()).getName());
		chargeItemVO.setBusinessCodeId(chargeItemDomain.getBizCode()==null?null:chargeItemDomain.getBizCode().getKeyword());
		chargeItemVO.setBusinessCodeName(chargeItemDomain.getBizCode()==null?null:chargeItemDomain.getBizCode().getBizCode());
		chargeItemVO.setBusinessDescription(chargeItemDomain.getBizCode()==null?null:chargeItemDomain.getBizCode().getBizCode()+"-"+chargeItemDomain.getBizCode().getDescription());
		chargeItemVO.setChrgTypeDisplay(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.FEE_CHAR_TYPE_CLASS_CODE,chargeItemDomain.getChrgType()).getName());
		chargeItemVO.setCreator(chargeItemDomain.getSysInfo()==null?null:chargeItemDomain.getSysInfo().getCreator());
		chargeItemVO.setModifier(chargeItemDomain.getSysInfo()==null?null:chargeItemDomain.getSysInfo().getModifier());
		chargeItemVO.setModifyDate(chargeItemDomain.getSysInfo()==null?null:chargeItemDomain.getSysInfo().getModifyDate());
		chargeItemVO.setSysDate(chargeItemDomain.getSysInfo()==null?null:chargeItemDomain.getSysInfo().getSysDate());
		return chargeItemVO;
	}
	/**
	 * 方法描述: ChargeItemVO to  ChargeItemDomain
	 * @author 胡煦
	 * Create on:2008-8-1
	 * @param ChargeItemVO
	 * @return chargeItemDomain
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	private ChargeItemDomain convertChargeItemV2D(ChargeItemVO chargeItemVO){
		ChargeItemDomain chargeItemDomain = new ChargeItemDomain();
		if(BlankUtil.isBlank(chargeItemVO)){
			return chargeItemDomain;
		}
		if(!BlankUtil.isBlank(chargeItemVO.getCreator())){
			SysInfo sysInfo = createInfo(chargeItemVO.getCreator());
			chargeItemDomain.setSysInfo(sysInfo);
		}
		if(!BlankUtil.isBlank(chargeItemVO.getKeyword())){
			chargeItemDomain = chargeItemDao.findById(chargeItemVO.getKeyword());
			if(!BlankUtil.isBlank(chargeItemVO.getModifier())){
				modifyInfo(chargeItemDomain.getSysInfo(), chargeItemVO.getModifier());
				chargeItemDomain.setSysInfo(chargeItemDomain.getSysInfo());
			}
		}
		PopulateUtil.populate(chargeItemVO, chargeItemDomain);
		chargeItemDomain.setBizCode(businessCodeDao.findById(chargeItemVO.getBusinessCodeId()));
		return chargeItemDomain;
	}

	/**
	 * 方法描述: 检查收费项目是否被引用,返回true说明被引用了，false则没有
	 *
	 * @author 胡煦 Create on:2008-7-30
	 * @param chargeItemId
	 * @return boolean
	 *  Edit author: Edit on: 修改原因：
	 */
	private boolean checkChargeItem(Long chargeItemId) {
		return chargeStaDao.queryAllChargeSatBy(chargeItemId).size() > 0;
	}

	/**
	 * 方法描述: 检查收费项目VO中必填项是否为空
	 * @author 胡煦
	 * Create on:2008-7-30
	 * @param chargeItemVO,key
	 * @return void
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	private void checkChargeItemVONotNullField(ChargeItemVO chargeItemVO,String key){
		if(chargeItemVO.getItemName() == null||chargeItemVO.getChrgType() == null ||chargeItemVO.getBusinessCodeId() == null){
			throw new BusinessException(key,BusinessException.WARNING);
		}
	}

	/***
	 * 功能描述:  获取指定类型的收费项目<br>
	 * @param chargeType
	 * @return
	 * Create author:yandawei <br>
	 * Create on:2008-10-22  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<ChargeItemVO> getAllChargeItemByType(String chargeType) {
		List<ChargeItemVO> chargeItemList = new ArrayList<ChargeItemVO>();
		List<ChargeItemDomain> list = chargeStaDao.findAllResult("from ChargeItemDomain chargeItem where chargeItem.chrgType=?", new String[]{chargeType});
		for (ChargeItemDomain domain : list) {
			chargeItemList.add(convertChargeItemD2V(domain));
		}
		return chargeItemList;
	}


	private IChargeItemDao chargeItemDao;
	private IBusinessCodeDao businessCodeDao;
	private IMeterDao meterDao;
	private IChargeStaDao chargeStaDao;

	/**
	 * @param chargeStaDao the chargeStaDao to set
	 */
	public void setChargeStaDao(IChargeStaDao chargeStaDao) {
		this.chargeStaDao = chargeStaDao;
	}
	/**
	 * @param businessCodeDao the businessCodeDao to set
	 */
	public void setBusinessCodeDao(IBusinessCodeDao businessCodeDao) {
		this.businessCodeDao = businessCodeDao;
	}

	/**
	 * @param chargeItemDao the chargeItemDao to set
	 */
	public void setChargeItemDao(IChargeItemDao chargeItemDao) {
		this.chargeItemDao = chargeItemDao;
	}
	/**
	 * @param meterDao the meterDao to set
	 */
	public void setMeterDao(IMeterDao meterDao) {
		this.meterDao = meterDao;
	}


}
